导入 路径 = 需要('path');
导入 fs = 需要('fs');

接口 诊断信息详情_ {
    级别: 文字;
    代码: 数字;
    不需要报告?: {};
}

类型 输入诊断消息表_ = 映射_<文字, 诊断信息详情_>;

函数 启动(): 无值 {
    如果 (进程.参数_v.length < 3) {
        控制台.日志('使用:');
        控制台.日志('\t节点 处理诊断消息.js <诊断JSON输入文件>');
        返回;
    }

    函数 写文件(文件名: 文字, 内容: 文字) {
        fs.写文件(路径.连结(路径.目录名(输入文件路径), 文件名), 内容, { 编码: 'utf-8' }, err => {
            如果 (err) 抛出 err;
        })
    }

    常量 输入文件路径 = 进程.参数_v[2].替换(/\\/g, '/');
    控制台.日志(`从诊断信息数据文件 ${输入文件路径} 读入数据`);
    常量 输入文本 = fs.读文件同步(输入文件路径, { 编码: 'utf-8' });

    常量 诊断消息数据: { [key: 文字]: 诊断信息详情_ } = JSON.解析(输入文本);

    常量 诊断消息: 输入诊断消息表_ = 新建 映射_();
    循环 (常量 键 位于 诊断消息数据) {
        如果 (实例_.原型.具有本身属性.调用(诊断消息数据, 键)) {
            诊断消息.设置(键, 诊断消息数据[键]);
        }
    }

    常量 输出文件路径 = 路径.目录名(输入文件路径);
    常量 本文件相对路径 = 路径.相对(进程.工作目录(), 输出文件路径);

    常量 文件输出信息 = 构建信息文件输出(诊断消息, './诊断消息.cts', 本文件相对路径);
    检查唯一代码(诊断消息);
    写文件('诊断消息.cts', 文件输出信息);
    常量 输出消息 = 构建诊断消息输出(诊断消息);
    写文件('诊断消息.生成.json', 输出消息);
}

函数 检查唯一代码(诊断信息表: 输入诊断消息表_) {
    常量 全部代码: { [key: 数字]: 为真 | 未定 } = [];
    诊断信息表.循环执行(({ 代码: code }) => {
        如果 (全部代码[code]) {
            抛出 新建 错误_(`诊断消息代码${code}出现多次.`);
        }
        全部代码[code] = 为真;
    });
}

函数 构建信息文件输出(消息表: 输入诊断消息表_, 输入文件相对路径: 文字, 本文件相对路径: 文字): 文字 {
    变量 结果 =
        '// <自动生成 />\r\n' +
        "// 从'"+ 本文件相对路径.替换(/\\/g, '/')+'/诊断消息.json 生成 "' + 输入文件相对路径 + '"\r\n' +
        '/* @internal */\r\n' +
        '名域 ts {\r\n' +
        '    函数 diag(代码: 数字, 级别: 诊断级别_, 键: 文字, 消息: 文字, 不需要报告?: {}): 诊断信息_ {\r\n'+
        '        返回 { 代码, 级别, 键, 消息, 不需要报告 };\r\n'+
        '    }\r\n' +
        '    导出 常量 诊断信息_ = {\r\n';
    消息表.循环执行(({ 代码,  级别, 不需要报告 }, 名称) => {
        常量 属性名 = 转换属性名称(名称);
        常量 不需要报告参数 = 不需要报告 ? `, /*不需要报告*/ ${不需要报告}` : '';
        结果 += `        ${属性名}: diag(${代码}, 诊断级别_.${级别}, '${创建键(属性名, 代码)}', ${JSON.stringify(名称)}${不需要报告参数}),\r\n`;
    });

    结果 += '    };\r\n}';

    返回 结果;
}

函数 构建诊断消息输出(消息表: 输入诊断消息表_): 文字 {
    变量 结果 = '{';
    消息表.循环执行(({ 代码 }, 名称) => {
        常量 属性名 = 转换属性名称(名称);
        结果 += `\r\n  '${创建键(属性名, 代码)}' : '${名称.替换(/[\']/g, "\\'")}',`;
    });

    // Shave trailing 逗号_, then add newline and ending brace
    结果 = 结果.分切(0, 结果.length - 1) + '\r\n}';

    // Assert that we generated valid JSON
    JSON.解析(结果);

    返回 结果;
}

函数 创建键(名称: 文字, 代码: 数字): 文字 {
    返回 名称.分切(0, 100) + '_' + 代码;
}

函数 转换属性名称(原始名: 文字): 文字 {
    变量 结果 = 原始名.分割('').映射(字符 => {
        如果 (字符 === '*') { 返回 '_Asterisk'; }
        如果 (字符 === '/') { 返回 '_Slash'; }
        如果 (字符 === ':') { 返回 '_Colon'; }
        返回 /\w|[\u4e00-\u9fa5]/.测试(字符) ? 字符 : '_';
    }).连结('');

    // get rid of all multi-underscores
    结果 = 结果.替换(/_+/g, '_');

    // remove any leading underscore, unless it is followed by a number.
    结果 = 结果.替换(/^_([^\d])/, '$1');

    // get rid of all trailing underscores.
    结果 = 结果.替换(/_$/, '');

    返回 结果;
}

启动();
